// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.assets.service.impl;

import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.constant.TimeFormatConstants;
import com.liuxinlong.enums.AssetsStatusEnum;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.assets.service.AssetsLockService;
import com.liuxinlong.modules.dao.AssetsAdvancePayDao;
import com.liuxinlong.modules.dao.AssetsCostDao;
import com.liuxinlong.modules.dao.AssetsDao;
import com.liuxinlong.modules.dao.AssetsLockDao;
import com.liuxinlong.modules.dao.AssetsMonthDetailDao;
import com.liuxinlong.modules.dao.AssetsOrderDao;
import com.liuxinlong.modules.dao.PatentDepartmentDao;
import com.liuxinlong.modules.dao.UserDao;
import com.liuxinlong.modules.entity.Assets;
import com.liuxinlong.modules.entity.AssetsAdvancePay;
import com.liuxinlong.modules.entity.AssetsCost;
import com.liuxinlong.modules.entity.AssetsLock;
import com.liuxinlong.modules.entity.AssetsMonthDetail;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import com.liuxinlong.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 固资项目预测锁定管理业务接口层实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2024-03-01
 */
@Service
@Slf4j
public class AssetsLockServiceImpl implements AssetsLockService {

    @Autowired
    private AssetsLockDao assetsLockDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private AssetsMonthDetailDao assetsMonthDetailDao;

    @Autowired
    private AssetsDao assetsDao;

    @Autowired
    private PatentDepartmentDao patentDepartmentDao;

    @Autowired
    private AssetsOrderDao assetsOrderDao;

    @Autowired
    private AssetsAdvancePayDao assetsAdvancePayDao;

    @Autowired
    private AssetsCostDao assetsCostDao;

    @Override
    @Transactional
    public List<Map<String, Object>> pageAssetsLockInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<AssetsLock> originalList = assetsLockDao.pageAssetsLockInfo(queryParam);
        List<Map<String, Object>> resultList = completeResult(originalList, startNum);
        return resultList;
    }

    @Override
    public int getAssetsLockInfoCount(Map<String, Object> queryParam) {
        return assetsLockDao.getAssetsLockInfoCount(queryParam);
    }

    @Override
    @Transactional
    public void addAssetsLockInfo(int confirmFlag) {
        String currentTime = TimeUtils.getDate(TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
        if (confirmFlag != 1) {
            AssetsLock latestRecord = assetsLockDao.getLatestRecord();
            if (!ObjectUtils.isEmpty(latestRecord)) {
                float days = TimeUtils.calculateTimeGapDay(currentTime, latestRecord.getOperateTime(), TimeFormatConstants.YYYY_MM_DD_HH_MM_SS);
                if (days < 60) {
                    throw new AosException(ReturnCodes.HTTP_SHORT_INTERVAL_TIME, "距离上次快照生成时间不足60天");
                }
            }
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);

        Map<String, Object> queryParam = new HashMap<>();
        String lockId = SnowFlake.nextIdStr();

        // 资产月度预测数据锁定
        List<AssetsMonthDetail> forecastList = assetsMonthDetailDao.getEffectiveMonthInfo(queryParam);
        List<AssetsMonthDetail> updateForecastList = new ArrayList<>(forecastList.size());
        for (AssetsMonthDetail detail : forecastList) {
            AssetsMonthDetail newDetail = new AssetsMonthDetail(detail);
            newDetail.setId(SnowFlake.nextIdStr());
            newDetail.setLockId(lockId);
            newDetail.setUpdateUser(currentUser.getId());
            newDetail.setUpdateTime(currentTime);
            updateForecastList.add(newDetail);
        }
        if (!ObjectUtils.isEmpty(updateForecastList)) {
            assetsMonthDetailDao.insertBatch(updateForecastList);
        }

        // 资产订单数据锁定(订单数据不锁，最新状态订单，预测数据锁定)
//        List<AssetsOrder> orderList = assetsOrderDao.getEffectiveOrderInfo(queryParam);

        // 资产花费数据锁定
        List<AssetsCost> costList = assetsCostDao.getEffectiveCostInfo();
        List<AssetsCost> updateCostList = new ArrayList<>(costList.size());
        for (AssetsCost cost : costList) {
            AssetsCost newCost = org.apache.commons.lang3.ObjectUtils.clone(cost);
            newCost.setId(SnowFlake.nextIdStr());
            newCost.setLockId(lockId);
            newCost.setUpdateUser(currentUser.getId());
            newCost.setUpdateTime(currentTime);
            updateCostList.add(newCost);
        }
        if (!ObjectUtils.isEmpty(updateCostList)) {
            assetsCostDao.insertBatch(updateCostList);
        }
        // 资产预付数据锁定
        List<AssetsAdvancePay> advancePayList = assetsAdvancePayDao.getEffectiveList();
        List<AssetsAdvancePay> updatePayList = new ArrayList<>(advancePayList.size());
        for (AssetsAdvancePay advancePay : advancePayList) {
            AssetsAdvancePay newPay = org.apache.commons.lang3.ObjectUtils.clone(advancePay);
            newPay.setId(SnowFlake.nextIdStr());
            newPay.setLockId(lockId);
            newPay.setUpdateUser(currentUser.getId());
            newPay.setUpdateTime(currentTime);
            updatePayList.add(newPay);
        }
        if (!ObjectUtils.isEmpty(updatePayList)) {
            assetsAdvancePayDao.insertBatch(updatePayList);
        }

        // 添加快照记录
        AssetsLock assetsLock = new AssetsLock();
        assetsLock.setId(lockId);
        assetsLock.setStatus(1);
        assetsLock.setOperateUser(currentUser.getId());
        assetsLock.setOperateTime(currentTime);
        assetsLockDao.insert(assetsLock);
    }

    @Override
    @Transactional
    public void updateAssetsLockInfo(AssetsLock assetsLock) {

    }

    @Override
    @Transactional
    public void deleteAssetsLockInfo(String id) {
        AssetsLock assetsLock = assetsLockDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsLock)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "删除失败，固资项目预测锁定信息不存在！");
        }
        assetsLock.setStatus(2);
        assetsLockDao.updateById(assetsLock);
    }

    @Override
    public void exportAssetsLock(Map<String, Object> queryParam, HttpServletResponse response) {

    }

    @Override
    public List<Map<String, Object>> getAssetsLockInfo(String id) {
        AssetsLock assetsLock = assetsLockDao.selectById(id);
        if (ObjectUtils.isEmpty(assetsLock)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "查询失败，固资项目预测锁定信息不存在！");
        }
        List<AssetsMonthDetail> monthDetailList = assetsMonthDetailDao.getLockMonthInfo(id);
        Map<String, Map<Integer, AssetsMonthDetail>> monthDetailMap = new HashMap<>();
        for (AssetsMonthDetail monthDetail : monthDetailList) {
            String assetsId = monthDetail.getBusinessId();
            Map<Integer, AssetsMonthDetail> detailMap = monthDetailMap.containsKey(assetsId) ? monthDetailMap.get(assetsId) : new HashMap<>();
            detailMap.put(monthDetail.getBusinessType(), monthDetail);
            monthDetailMap.put(assetsId, detailMap);
        }
        // 获取全部固资项目
        List<Assets> assetsList = assetsDao.getAllAssetsList();
        Map<String, Assets> assetsMap = new HashMap<>(assetsList.size());
        for (Assets assets : assetsList) {
            assetsMap.put(assets.getId(), assets);
        }
        List<Map<String, Object>> dataList = new ArrayList<>(monthDetailMap.size());
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        Map<String, Map<String, String>> departmentMap = patentDepartmentDao.getDepartmentMap();
        // 拼装数据
        int sort = 1;
        for (String assetsId : monthDetailMap.keySet()) {
            // 主数据
            if (!assetsMap.containsKey(assetsId)) {
                continue;
            }
            Assets assets = assetsMap.get(assetsId);
            Map<String, Object> item = ObjectUtils.object2Map(assets);
            // 计划数据
            Map<Integer, AssetsMonthDetail> detailMap = monthDetailMap.get(assetsId);
            for (Integer type : detailMap.keySet()) {
                if (type == 1) {

                } else if (type == 2) {

                } else if (type == 3) {

                } else if (type == 4) {

                }
            }
            item.put("departmentName", departmentMap.containsKey(assets.getDepartment()) ? departmentMap.get(assets.getDepartment()).get("name") : "");
            item.put("manageName", userMap.containsKey(assets.getProjectManage()) ? userMap.get(assets.getProjectManage()).get("name") : "");
            item.put("statusName", AssetsStatusEnum.getNameByValue(assets.getStatus()));
            item.put("sort", sort);
            dataList.add(item);
            sort++;
        }
        return dataList;
    }

    @Override
    public void exportAssetsLockInfo(String id, HttpServletResponse response) {
        ExcelData data = new ExcelData();
        data.setFileName("固资预测数据导出excel.xlsx");
        List<Map<String, Object>> originalDataList = getAssetsLockInfo(id);
        String[] head = {"展示排序", "固资号", "申请部门", "项目描述", "项目负责人", "绿单总金额", "当年计划金额", "当年预测金额", "当年实际金额", "状态"};
        data.setHead(head);
        String[][] dataList = new String[originalDataList.size()][head.length];
        int index = 0;
        for (Map<String, Object> assetsInfo : originalDataList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = (String) assetsInfo.get("assetsNo");
            dataList[index][2] = (String) assetsInfo.get("departmentName");
            dataList[index][3] = (String) assetsInfo.get("projectName");
            dataList[index][4] = (String) assetsInfo.get("manageName");
            dataList[index][5] = String.valueOf(assetsInfo.get("greenAmount"));
            dataList[index][6] = String.valueOf(assetsInfo.get("currentYearAmount"));
            dataList[index][7] = String.valueOf(assetsInfo.get("currentYearForecast"));
            dataList[index][8] = String.valueOf(assetsInfo.get("currentYearActual"));
            dataList[index][9] = (String) assetsInfo.get("statusName");
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);
    }

    /**
     * 补全数据
     *
     * @param originalList 原始数据
     * @param startNum     数据起始值
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<AssetsLock> originalList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        Map<String, Map<String, String>> userMap = userDao.getUserMap();
        int sort = startNum + 1;
        for (AssetsLock assetsLock : originalList) {
            Map<String, Object> item = ObjectUtils.object2Map(assetsLock);
            item.put("sort", sort);
            item.put("operateUserName", userMap.containsKey(assetsLock.getOperateUser()) ?
                    userMap.get(assetsLock.getOperateUser()).get("name") : "");
            item.put("statusName", assetsLock.getStatus() == 1 ? "可用" : "不可用");
            resultList.add(item);
            sort++;
        }
        return resultList;
    }
}
